import java.util.ArrayList;
import java.util.Scanner;

/**
 * Created with IntelliJ IDEA.
 * Description: 相连的边
 * User: DELL
 * Date: 2024-05-09
 * Time: 16:22
 */
public class Main6 {
    static class Edge {
        int x1;
        int x2;
        int length;
        int index;

        public Edge(int x1, int x2, int length, int index) {
            this.x1 = x1;
            this.x2 = x2;
            this.length = length;
            this.index = index;
        }
    }

    /**
     * 因为这个题是找出相邻的三条边，使得三条边的长度和尽可能大，而针对一个树来说，
     * 三条边只可能有两种情况，即一个点上的三条边 和 一条边的两个端点再分别延申一条边
     * 因此，关于一个点的边的边长排序就比较关键，因为如果我们知道每一个点相连的边的
     * 最长的两条边，那么针对 一个点上的三条边 这种情况就可以直接遍历就可以找到最大的了，
     * 而对于 一条边的两个端点再分别延申一条边 这种情况，可以遍历每一条边，然后分别取
     * 两个端点的最长边即可。
     * 因此就建立一个该树的邻接表，使用ArrayList来存边即可。
     *
     * @param args
     */
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        ArrayList<Edge>[] edges = new ArrayList[n + 1];
        ArrayList<Edge> allEdge = new ArrayList<>();
        for (int i = 1; i < n; i++) {
            Edge edge = new Edge(i + 1, scanner.nextInt(), scanner.nextInt(), i);
            Edge edge2 = new Edge(edge.x2, i + 1, edge.length, i);
            if (edges[i + 1] == null) {
                edges[i + 1] = new ArrayList<>();
            }
            edges[i + 1].add(edge);
            if (edges[edge2.x1] == null) {
                edges[edge2.x1] = new ArrayList<>();
            }
            edges[edge2.x1].add(edge2);
            allEdge.add(edge);
        }
        // 针对每个点的连接边进行排序
        for (int i = 1; i <= n; i++) {
            if (edges[i] == null) continue;
            edges[i].sort((o1, o2) -> o2.length - o1.length);
        }
        // 遍历一个点连三条边的情况
        long ans = 0L;
        for (int i = 1; i < n; i++) {
            if (edges[i] == null || edges[i].size() <= 2) {
                continue;
            }
            ans = Math.max(ans, (long) edges[i].get(0).length + edges[i].get(1).length + edges[i].get(2).length);
        }
        // 遍历一条边的两个端点再分别延申一条边
        for (int i = 0; i < allEdge.size(); i++) {
            Edge edge = allEdge.get(i);
            if (edges[edge.x1] == null || edges[edge.x2] == null) continue;
            Edge edge1 = edges[edge.x1].get(0);
            Edge edge2 = edges[edge.x2].get(0);
            if (edge1.index == edge.index) {
                if (edges[edge.x1].size() <= 1) {
                    continue;
                } else {
                    edge1 = edges[edge.x1].get(1);
                }
            }
            if (edge2.index == edge.index) {
                if (edges[edge.x2].size() <= 1) {
                    continue;
                } else {
                    edge2 = edges[edge.x2].get(1);
                }
            }
            ans = Math.max(ans, (long) edge.length + edge1.length + edge2.length);
        }
        System.out.println(ans);
    }

}
